﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Specialized;
using System.Net;
namespace Bitstar.YahooImport
{
   
        public class YahooContactImport
        {
            private const string _addressBookUrl = "http://address.yahoo.com/yab/us/Yahoo_ab.csv?loc=us&.rand=1671497644&A=H&Yahoo_ab.csv";
            private const string _authUrl = "https://login.yahoo.com/config/login?";
            //private const string _loginPage = "https://login.yahoo.com/config/login";
            private const string _loginPage = "https://login.yahoo.com/config/login_verify2?&.src=ym";            
            private const string _userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3";

            

            public MailContactList ExtractContacts(string username, string password)
            {               

                MailContactList list = new MailContactList();

                
                    WebClient webClient = new WebClient();
                    webClient.Headers[HttpRequestHeader.UserAgent] = _userAgent;
                    webClient.Encoding = Encoding.UTF8;

                    byte[] firstResponse = webClient.DownloadData(_loginPage);
                    string firstRes = Encoding.UTF8.GetString(firstResponse);


                    NameValueCollection postToLogin = new NameValueCollection();
                    Regex regex = new Regex("type=\"hidden\" name=\"(.*?)\" value=\"(.*?)\"", RegexOptions.IgnoreCase);
                    Match match = regex.Match(firstRes);
                    while (match.Success)
                    {
                        if (match.Groups[0].Value.Length > 0)
                        {
                            postToLogin.Add(match.Groups[1].Value, match.Groups[2].Value);
                        }
                        match = regex.Match(firstRes, match.Index + match.Length);
                    }

                    // oare de ce au nevoie astia de atatea variabile inutile doar pt a imi complica mie viata?
                    postToLogin.Add(".save", "Sign In");
                    //postToLogin.Add(".persistent", "y");

                    string login = username.Split('@')[0];
                    postToLogin.Add("login", login);
                    postToLogin.Add("passwd", password);

                    // mai jos este codul vechi care mergea ok dar nu mai stia ce sa faca daca intalnea redirect 302
                    /*webClient.Headers[HttpRequestHeader.UserAgent] = _userAgent;
                    webClient.Headers[HttpRequestHeader.Referer] = _loginPage;
                    webClient.Encoding = Encoding.UTF8;
                    webClient.Headers[HttpRequestHeader.Cookie] = webClient.ResponseHeaders[HttpResponseHeader.SetCookie];                    
                    byte[] temp = webClient.UploadValues(_authUrl, postToLogin);
                    string ret = Encoding.UTF8.GetString(temp);
                    string cookie = webClient.ResponseHeaders[HttpResponseHeader.SetCookie];*/

                    /* cod nou rescris */
                    // <magic type="voodoo" text="cand am scris codul stim ce ii in el, dar daca apare vreo problema in el nu ma intreba">
                    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(_authUrl);
                    req.AllowAutoRedirect = false;
                    req.Headers[HttpRequestHeader.Cookie] = webClient.ResponseHeaders[HttpResponseHeader.SetCookie];                    
                    req.Referer = _loginPage;
                    req.Method = "POST";
                    req.ContentType = "application/x-www-form-urlencoded";
                
                    ASCIIEncoding encoding = new ASCIIEncoding();
                    string postData = "";
                    for (int i = 0; i < postToLogin.Count; i++)
                    {
                        postData += postToLogin.Keys[i] + "=" + postToLogin.GetValues(i)[0];
                        if (i != postToLogin.Count) postData += "&";
                    }
                    req.ContentLength = postData.Length;
                    System.IO.Stream str2 = req.GetRequestStream();
                    str2.Write(encoding.GetBytes(postData), 0, postData.Length);
                    str2.Close();
                    HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                    System.IO.StreamReader str = new System.IO.StreamReader(resp.GetResponseStream());
                    string ret = str.ReadToEnd();
                    // </magic>  
                    
                    if (ret.Contains("Invalid ID or password") || ret.Contains("Please try again using your full Yahoo! ID"))
                        throw new InvalidPassOrUsernameException();

                    // bine ca nu mai avem nevoie de cookie parser - codul merge si fara - desi stie sfantu cum
                    // sincer nu ar trebuie sa mearga - chiar nu e in formatul corect!!!! Oricum nu ma plang
                    // asa arata campul cookies primit!                    
                    //"YLS=v=1&p=0&n=1; expires=Tue, 02-Jun-2037 20:00:00 GMT; path=/; domain=.yahoo.com,F=a=rzihSW8MvTEIdXLCA4XvXZJN4Chk78Sb2Ok_c6_2JGMyfjdhHampu4D9pNkkFqWXRJXFdn4-&b=IrS_; expires=Tue, 02-Jun-2037 20:00:00 GMT; path=/; domain=.yahoo.com,Y=v=1&n=87r633aaj172k&l=7fhe54j/o&p=m2mvvro013000000&iz=3400&r=dp&lg=en-US&intl=us&np=1; path=/; domain=.yahoo.com,PH=fn=Wy.T0FCsOGZ8p4hXZLg-&l=en-US; expires=Tue, 02-Jun-2037 20:00:00 GMT; path=/; domain=.yahoo.com,T=z=bLVwJBbf80JBBR/l.WQNVjFMk8xBjY0NzI1NTMwM04-&a=QAE&sk=DAAy4Plsvvl8z8&ks=EAADS4Fff9rut_5uDVquLEfAA--~C&d=c2wBTlRnMkFURXpNRFV5TWpRM05Eay0BYQFRQUUBZwFLTVdOMjNFWkdCRDVZT09PRjdET1UzVTc0VQF0aXABWmhvTkVEAXp6AWJMVndKQkE3RQ--; path=/; domain=.yahoo.com"
                    string cookie = resp.Headers["Set-Cookie"];
                     
                    if (string.IsNullOrEmpty(cookie))
                    {   

                        throw new UnexpectedResponseException("No cookie returned after login! Login interface may have changed! Contact the developers for an update.");
                        return null;// poate ar fi mai util sa imi trimit un mail sa ma atentionez ca ceva nu mai merge.....neah....send to /dev/null
                    }

                    string newCookie = string.Empty;
                    string[] tmp1 = cookie.Split(',');
                    foreach (string var in tmp1)
                    {
                        string[] tmp2 = var.Split(';');
                        newCookie = String.IsNullOrEmpty(newCookie) ? tmp2[0] : newCookie + ";" + tmp2[0];
                    }

                    // set login cookie
                    webClient.Headers[HttpRequestHeader.Cookie] = newCookie;
                    byte[] thirdResponse = webClient.DownloadData(_addressBookUrl);
                    string thirdRes = Encoding.UTF8.GetString(thirdResponse);

                    string crumb = string.Empty;
                    // don't ask :P
                    Regex regexCrumb = new Regex("type=\"hidden\" name=\"\\.crumb\" id=\"crumb1\" value=\"(.*?)\"", RegexOptions.IgnoreCase);
                    match = regexCrumb.Match(thirdRes);
                    if (match.Success && match.Groups[0].Value.Length > 0)
                    {
                        crumb = match.Groups[1].Value;
                    }


                    NameValueCollection postDataAB = new NameValueCollection();
                    postDataAB.Add(".crumb", crumb);
                    postDataAB.Add("vcp", "import_export");
                    postDataAB.Add("submit[action_export_yahoo]", "Export Now");

                    webClient.Headers[HttpRequestHeader.UserAgent] = _userAgent;
                    webClient.Headers[HttpRequestHeader.Referer] = _addressBookUrl;

                    byte[] FourResponse = webClient.UploadValues(_addressBookUrl, postDataAB);
                    string csvData = Encoding.UTF8.GetString(FourResponse);

                    string[] lines = csvData.Split('\n');
                    int index = 0;
                    foreach (string line in lines)
                    {
                        string[] items = line.Split(',');
                        if (items.Length < 5)
                        {
                            continue;
                        }
                        string first = items[0];
                        string last = items[2];
                        string email = items[4];
                        string name = items[3];
                        string mid = items[7];

                        email = email.Trim('\"');
                        name = name.Trim('\"');
                        mid = mid.Trim('\"');
                        first = first.Trim('\"');
                        last = last.Trim('\"');

                        if (!string.IsNullOrEmpty(email) || !string.IsNullOrEmpty(mid))
                        {
                            
                            if (index == 0)
                            {
                                if (!email.Equals("Email") && !name.Equals("Nickname") && !mid.Equals("Messenger ID"))
                                    throw new UnexpectedResponseException("The format of the CVS data returned by Yahoo has changed! Contact the developers for an update");
                            }
                            index++;


                            if (!email.Equals("Email") && !name.Equals("Nickname") && !mid.Equals("Messenger ID"))
                            {
                                MailContact mailContact = new MailContact();
                                if (!string.IsNullOrEmpty(first) || !string.IsNullOrEmpty(last))
                                    mailContact.Name = first+" "+last;
                                else
                                    mailContact.Name = name;
                                mailContact.Email = email;
                                mailContact.MessengerID = mid;
                                list.Add(mailContact);
                            }
                        }
                    }
                    return list;
                }
                

            }

        /// <summary>
        /// NO COMMENT
        /// </summary>
        class CookieParser
        {
            string header;
            int pos;
            int length;

            public CookieParser(string header)
                : this(header, 0)
            {
            }

            public CookieParser(string header, int position)
            {
                this.header = header;
                this.pos = position;
                this.length = header.Length;
            }

            public bool GetNextNameValue(out string name, out string val)
            {
                name = null;
                val = null;

                if (pos >= length)
                    return false;

                name = GetCookieName();
                if (pos < header.Length && header[pos] == '=')
                {
                    pos++;
                    val = GetCookieValue();
                }

                if (pos < length && header[pos] == ';')
                    pos++;

                return true;
            }

            string GetCookieName()
            {
                int k = pos;
                while (k < length && Char.IsWhiteSpace(header[k]))
                    k++;

                int begin = k;
                while (k < length && header[k] != ';' && header[k] != '=')
                    k++;

                pos = k;
                return header.Substring(begin, k - begin).Trim();
            }

            string GetCookieValue()
            {
                if (pos >= length)
                    return null;

                int k = pos;
                while (k < length && Char.IsWhiteSpace(header[k]))
                    k++;

                int begin;
                if (header[k] == '"')
                {
                    int j;
                    begin = ++k;

                    while (k < length && header[k] != '"')
                        k++;

                    for (j = k; j < length && header[j] != ';'; j++)
                        ;
                    pos = j;
                }
                else
                {
                    begin = k;
                    while (k < length && header[k] != ';')
                        k++;
                    pos = k;
                }

                return header.Substring(begin, k - begin).Trim();
            }
        }


}
